package login.logic;

import java.io.IOException;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import game.module.user.ProtoMessageLogin.S2CGarenaLogin;
import game.module.user.ProtoMessageLogin.S2CGuestLogin;
import game.module.user.ProtoMessageLogin.S2CLogin;
import game.module.user.ProtoMessageLogin.S2CQQLogin;
import game.module.user.ProtoMessageLogin.S2CSifubaLogin;
import game.module.user.ProtoMessageLogin.S2CYiJieLogin;
import game.module.user.ProtoMessageLogin.S2CYunDingLogin;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import lion.netty4.message.GamePlayer;
import lion.netty4.proto.RpcBaseProto.RetCode;
import login.LoginServer;
import login.bean.GarenaLoginSessionBean;
import login.bean.LoginClientSessionBean;
import login.bean.QqLoginSessionBean;
import login.bean.SifubaLoginSessionBean;
import login.bean.ZyLoginSessionBean;
import login.dao.LoginAccountDao;
import login.stat.LoginStat;
import lua.LuaMessageLogin.S2COpenLogin;
import lua.LuaMessageLogin.S2ErrorCode;
import sdk.garena.GarenaOauthApi;
import sdk.zy.WeiXinOpenApi;
import sdk.zy.YijieApi;
import sdk.zy.YunDingApi;

public class LoginAccountManager {

	private static Logger logger = LoggerFactory.getLogger(LoginAccountManager.class);

	static class SingletonHolder {
		static LoginAccountManager instance = new LoginAccountManager();
	}

	public static LoginAccountManager getInstance() {
		return SingletonHolder.instance;
	}

	public void insert1KAccount() {
		for (int i = 0; i < 1000; i++) {
			LoginAccountDao.getInstance().insertLoginAccount(String.valueOf(i), String.valueOf(1));
		}
	}

	public void login(final GamePlayer gamePlayer, String deviceId, final String userName, final String pwd,
			String loginIp) {
		LoginServer.executorService.execute(new Runnable() {
			@Override
			public void run() {
				boolean existUser = LoginAccountDao.getInstance().checkExist(userName, pwd);
				if (!existUser) {
					gamePlayer.writeAndFlush(10014, RetCode.LOGIN_NAME_NOT_EXIST);
				} else {
					int uid = LoginAccountDao.getInstance().getUidByNamePwd(userName, pwd);
					long sessionId = LoginServer.getInstance().generateRandomId();
					// tmp save
					LoginClientSessionBean clientSessionBean = new LoginClientSessionBean(uid, sessionId);
					gamePlayer.getChannel().attr(LoginServer.KEY_LOGIN_SESSION_INFO).set(clientSessionBean);
					S2CLogin.Builder respBuilder = S2CLogin.newBuilder();
					// playerDao.updateLoginIp(loginIp, ub.getId());
					respBuilder.setUid(uid).setSessionId(sessionId);
					gamePlayer.writeAndFlush(10014, respBuilder.build());
					LoginStat.getInstance().statLogin(userName);
				}
			}
		});
	}

	public void garenaLogin(final GamePlayer gamePlayer, final String accessToken) {
		LoginServer.executorService.execute(new Runnable() {
			@Override
			public void run() {
				try {
					Map<String, Object> retMap = GarenaOauthApi.getInstance().inspectAccessToken(accessToken);
					if (retMap == null) {
						logger.warn("network error!");
						gamePlayer.writeAndFlush(10022, RetCode.GARENA_LOGIN_NETWORK_ERROR);
						return;
					}
					if (retMap.containsKey("error")) {
						logger.warn("error:{}", retMap.get("error"));
						gamePlayer.writeAndFlush(10022, RetCode.USER_ACCESS_TOKEN_INVALID);
					} else {
						logger.info("garena inspect accessToken ret={}", retMap.toString());
						// uint8 platform
						// uint64 uid / string open_id: user id or open id,
						// depends on app
						String openId = (String) retMap.get("open_id");
						long sessionId = LoginServer.getInstance().generateRandomId();
						LoginClientSessionBean clientSessionBean = new GarenaLoginSessionBean(openId, sessionId,
								accessToken);
						gamePlayer.getChannel().attr(LoginServer.KEY_LOGIN_SESSION_INFO).set(clientSessionBean);
						gamePlayer.writeAndFlush(10022, S2CGarenaLogin.newBuilder().setSessionId(sessionId).build());
						LoginStat.getInstance().statLogin(accessToken);
					}
				} catch (IOException e) {
					logger.error("", e);
				}
			}
		});
	}

	public void sifubaLogin(GamePlayer gamePlayer, String userId) {
		long sessionId = LoginServer.getInstance().generateRandomId();
		LoginClientSessionBean clientSessionBean = new SifubaLoginSessionBean(userId, sessionId);
		gamePlayer.getChannel().attr(LoginServer.KEY_LOGIN_SESSION_INFO).set(clientSessionBean);
		gamePlayer.writeAndFlush(10026, S2CSifubaLogin.newBuilder().setSessionId(sessionId));
	}

	public void qqLogin(final GamePlayer gamePlayer, final String qqOpenId, final String accessToken) {
		// if (qqOpenApiV3 == null) {
		// qqOpenApiV3 = new
		// OpenApiV3(LoginServer.getInstance().getLoginServerConfig().getQqAppId(),
		// LoginServer.getInstance().getLoginServerConfig().getQqAppKey());
		// qqOpenApiV3.setServerName("openapi.tencentyun.com");
		// // qqOpenApiV3.setServerName("119.147.19.43");
		// }
		// LoginServer.executorService.execute(new Runnable() {
		// @SuppressWarnings("unchecked")
		// @Override
		// public void run() {
		// try {
		// // 指定OpenApi Cgi名字
		// String scriptName = "/v3/user/is_login";
		//
		// // 指定HTTP请求协议类型
		// String protocol = "http";
		//
		// // 填充URL请求参数
		// HashMap<String, String> params = new HashMap<String, String>();
		// params.put("openid", qqOpenId);
		// params.put("openkey", accessToken);
		// params.put("pf", "qzone");
		//
		// String resp = qqOpenApiV3.api(scriptName, params, protocol);
		// logger.error("qq oauth response={}", resp);
		//
		// Map<String, Object> retMap = new ObjectMapper().readValue(resp,
		// Map.class);
		// if (!retMap.containsKey("ret")) {
		// gamePlayer.writeAndFlush(10030, RetCode.USER_ACCESS_TOKEN_INVALID);
		// return;
		// }
		// Integer retCode = (Integer) retMap.get("ret");
		// if (retCode != 0) {
		// gamePlayer.writeAndFlush(10030, RetCode.USER_ACCESS_TOKEN_INVALID);
		// return;
		// }
		// // 返回成功
		// long sessionId = LoginServer.getInstance().generateRandomId();
		// LoginClientSessionBean clientSessionBean = new
		// QqLoginSessionBean(qqOpenId, sessionId);
		// gamePlayer.getChannel().attr(LoginServer.KEY_LOGIN_SESSION_INFO).set(clientSessionBean);
		// // ret
		// gamePlayer.writeAndFlush(10030,
		// S2CQQLogin.newBuilder().setSessionId(sessionId).build());
		// LoginStat.getInstance().statLogin(accessToken);
		// } catch (Exception e) {
		// logger.error("", e);
		// gamePlayer.writeAndFlush(10030, RetCode.GARENA_LOGIN_NETWORK_ERROR);
		// return;
		// }
		// }
		// });
		long sessionId = LoginServer.getInstance().generateRandomId();
		LoginClientSessionBean clientSessionBean = new QqLoginSessionBean(qqOpenId, sessionId);
		gamePlayer.getChannel().attr(LoginServer.KEY_LOGIN_SESSION_INFO).set(clientSessionBean);
		// ret
		gamePlayer.writeAndFlush(10030, S2CQQLogin.newBuilder().setSessionId(sessionId).build());
		LoginStat.getInstance().statLogin(accessToken);
	}

	public void zyLogin(final GamePlayer gamePlayer, final String zyUserId, final String accessToken) {
		// LoginServer.executorService.execute(new Runnable() {
		// @Override
		// public void run() {
		// try {
		// String appKey =
		// LoginServer.getInstance().getLoginServerConfig().getZyAppKey();
		// String zyUrlBase =
		// LoginServer.getInstance().getLoginServerConfig().getZyUrlBase();
		// Map<String, Object> retMap =
		// DaLanApi.getInstance().verifyLogin(zyUserId, accessToken, appKey,
		// zyUrlBase);
		// if (retMap == null) {
		// logger.warn("network error!");
		// gamePlayer.writeAndFlush(10032, RetCode.GARENA_LOGIN_NETWORK_ERROR);
		// return;
		// }
		// logger.info("zy inspect token result={}", retMap);
		// if (!retMap.containsKey("state") || (int) retMap.get("state") != 1) {
		// logger.warn("error:{}", retMap.get("error"));
		// gamePlayer.writeAndFlush(10032, RetCode.USER_ACCESS_TOKEN_INVALID);
		// return;
		// }
		// Object userIdObj = (((Map<String, Object>)
		// retMap.get("data")).get("userID"));
		// long sessionId = LoginServer.getInstance().generateRandomId();
		// LoginClientSessionBean clientSessionBean = new
		// ZyLoginSessionBean(String.valueOf(userIdObj),
		// sessionId);
		// gamePlayer.getChannel().attr(LoginServer.KEY_LOGIN_SESSION_INFO).set(clientSessionBean);
		// gamePlayer.writeAndFlush(10032,
		// S2CZyLogin.newBuilder().setSessionId(sessionId).build());
		// LoginStat.getInstance().statLogin(accessToken);
		// } catch (Exception e) {
		// logger.error("", e);
		// gamePlayer.writeAndFlush(10032, RetCode.GARENA_LOGIN_NETWORK_ERROR);
		// }
		// }
		// });
	}

	/**
	 * 游客登录
	 * 
	 * @param player
	 * @param accountId
	 */
	public void guestLogin(final GamePlayer gamePlayer, final int accountId) {
		LoginServer.executorService.execute(new Runnable() {
			@Override
			public void run() {
				// 创建账号
				int targetAccount = accountId;
				if (targetAccount == 0) {
					targetAccount = LoginAccountDao.getInstance().insertLoginAccount("guest", "1");
				} else {
					// checkExist
					boolean existUser = LoginAccountDao.getInstance().checkGuestExist(targetAccount);
					if (!existUser) {
						S2ErrorCode retMsg = new S2ErrorCode(RetCode.LOGIN_NAME_NOT_EXIST.getNumber());
						gamePlayer.writeAndFlush(retMsg.build(gamePlayer.alloc()));
						return;
					}
				}
				final long sessionId = LoginServer.getInstance().generateRandomId();
				//
				final String hsSocketHost = LoginServer.getInstance().getLoginServerConfig().getHallServerSocketHost();
				final int hsPort = LoginServer.getInstance().getLoginServerConfig().getHallServerSocketPort();
				String hsLanHost = LoginServer.getInstance().getLoginServerConfig().getHallServerLanHost();
				int hsLanPort = LoginServer.getInstance().getLoginServerConfig().getHallServerLanPort();
				boolean reconnectRet = LoginServer.getInstance().getLanClientManager().connect(hsLanHost, hsLanPort);
				if (reconnectRet) {
					ChannelFuture channelFuture = LoginServer.getInstance().getLanClientManager().sendMessage(hsLanHost,
							hsLanPort, sessionId, (int) (targetAccount), 1);
					// 等待结束
					final int accountId = targetAccount;
					channelFuture.addListener(new ChannelFutureListener() {
						@Override
						public void operationComplete(ChannelFuture channelFuture) throws Exception {
							lua.LuaMessageLogin.S2CGuestLogin retMsg = new lua.LuaMessageLogin.S2CGuestLogin(
									accountId, hsSocketHost, sessionId, 0, hsPort);
							if (channelFuture.isCancelled()) {
								retMsg.is_success = 2;
							} else if (!channelFuture.isSuccess()) {
								logger.error("", channelFuture.cause());
								retMsg.is_success = 3;
							}
							gamePlayer.writeAndFlush(retMsg.build(gamePlayer.alloc()));
							LoginStat.getInstance().statLogin(String.valueOf(accountId));
						}
					});
				} else {
					lua.LuaMessageLogin.S2CGuestLogin retMsg = new lua.LuaMessageLogin.S2CGuestLogin(targetAccount,
							hsSocketHost, sessionId, 1, hsPort);
					gamePlayer.writeAndFlush(retMsg.build(gamePlayer.alloc()));
					LoginStat.getInstance().statLogin(String.valueOf(targetAccount));
				}
			}
		});

	}

	public void yunDingLogin(final GamePlayer gamePlayer, final int uid, final String userToken) {
		LoginServer.executorService.execute(new Runnable() {
			@Override
			public void run() {
				try {
					int v = 2;
					int gact = 118;
					int appid = 6220;
					Map<String, Object> retMap = YunDingApi.getInstance().verifylogin("http://ins.app-fame.com", v,
							gact, appid, uid, userToken);
					if (retMap == null) {
						logger.warn("network error!");
						gamePlayer.writeAndFlush(10042,
								S2CYunDingLogin.newBuilder().setRet(RetCode.GARENA_LOGIN_NETWORK_ERROR_VALUE));
						return;
					}
					logger.info("yunding inspect session result={}", retMap);
					if (!retMap.containsKey("result") || !((String) retMap.get("result")).equals("1")) {
						logger.warn("error:{}", retMap.get("error"));
						gamePlayer.writeAndFlush(10042,
								S2CYunDingLogin.newBuilder().setRet(RetCode.USER_ACCESS_TOKEN_INVALID_VALUE));
						return;
					}
					long sessionId = LoginServer.getInstance().generateRandomId();
					LoginClientSessionBean clientSessionBean = new ZyLoginSessionBean(String.valueOf(uid), sessionId);
					gamePlayer.getChannel().attr(LoginServer.KEY_LOGIN_SESSION_INFO).set(clientSessionBean);
					gamePlayer.writeAndFlush(10042, S2CYunDingLogin.newBuilder().setRet(RetCode.RET_OK_VALUE)
							.setUid(uid).setSessionId(sessionId).setUserToken(userToken));
					LoginStat.getInstance().statLogin(userToken);
				} catch (Exception e) {
					logger.error("", e);
					gamePlayer.writeAndFlush(10042,
							S2CYunDingLogin.newBuilder().setRet(RetCode.GARENA_LOGIN_NETWORK_ERROR_VALUE));
				}
			}
		});
	}

	public void yijieLogin(final GamePlayer gamePlayer, final String uin, final String sess, final String channelid) {
		LoginServer.executorService.execute(new Runnable() {
			@Override
			public void run() {
				try {
					String appId = "FA5EA47AAD412242";
					String dalanUrlBase = "http://sync.1sdk.cn/login/check.html";
					String newChannelid = StringUtils.remove(channelid, '{');
					newChannelid = StringUtils.remove(newChannelid, '}');
					newChannelid = StringUtils.remove(newChannelid, '-');
					String retStr = YijieApi.getInstance().verifylogin(newChannelid, appId, uin, sess, dalanUrlBase);
					if (retStr == null) {
						logger.warn("network error!");
						gamePlayer.writeAndFlush(10052,
								S2CYiJieLogin.newBuilder().setRet(RetCode.GARENA_LOGIN_NETWORK_ERROR_VALUE));
						return;
					}
					logger.info("yijie inspect session result={}", retStr);
					if (!retStr.equals("0")) {
						logger.warn("error:{}", retStr);
						gamePlayer.writeAndFlush(10052,
								S2CYiJieLogin.newBuilder().setRet(RetCode.USER_ACCESS_TOKEN_INVALID_VALUE));
						return;
					}
					long sessionId = LoginServer.getInstance().generateRandomId();
					LoginClientSessionBean clientSessionBean = new ZyLoginSessionBean(uin, sessionId);
					gamePlayer.getChannel().attr(LoginServer.KEY_LOGIN_SESSION_INFO).set(clientSessionBean);
					gamePlayer.writeAndFlush(10052, S2CYiJieLogin.newBuilder().setRet(RetCode.RET_OK_VALUE)
							.setSessionId(sessionId).setUin(uin));
					LoginStat.getInstance().statLogin(sess);
				} catch (Exception e) {
					logger.error("", e);
					gamePlayer.writeAndFlush(10052,
							S2CYiJieLogin.newBuilder().setRet(RetCode.GARENA_LOGIN_NETWORK_ERROR_VALUE));
				}
			}
		});
	}

	public void loginWeiXin(final GamePlayer gamePlayer, final String code, final String refresh_token) {
		LoginServer.executorService.execute(new Runnable() {
			@Override
			public void run() {
				String new_refresh_token = null;
				String access_token = "";
				String open_id = null;
				if (StringUtils.isEmpty(code)) {
					String appId = LoginServer.getInstance().getLoginServerConfig().getWeiXinAppId();
					Map<String, Object> retMap = WeiXinOpenApi.getInstance().refreshToken(appId, refresh_token);
					if (retMap.containsKey("errcode")) {
						logger.info("weixin login refreshToken error!ret={}", retMap);
						S2COpenLogin retMsg = new S2COpenLogin(refresh_token, "", "", 0L, 2, 0);
						gamePlayer.writeAndFlush(retMsg.build(gamePlayer.alloc()));
						return;
					} else {
						new_refresh_token = (String) retMap.get("refresh_token");
						open_id = (String) retMap.get("openid");
						access_token = (String) retMap.get("access_token");
					}
				} else {
					String appId = LoginServer.getInstance().getLoginServerConfig().getWeiXinAppId();
					String appSecret = LoginServer.getInstance().getLoginServerConfig().getWeiXinAppSecret();
					Map<String, Object> retMap = WeiXinOpenApi.getInstance().verifylogin(appId, appSecret, code);
					if (retMap.containsKey("errcode")) {
						logger.info("weixin login verify code error!ret={}", retMap);
						S2COpenLogin retMsg = new S2COpenLogin(refresh_token, "", "", 0L, 3, 0);
						gamePlayer.writeAndFlush(retMsg.build(gamePlayer.alloc()));
						return;
					} else {
						new_refresh_token = (String) retMap.get("refresh_token");
						open_id = (String) retMap.get("openid");
						access_token = (String) retMap.get("access_token");
					}
				}
				final String fixed_refresh_token = new_refresh_token;
				final String fixed_open_id = open_id;
				final long sessionId = LoginServer.getInstance().generateRandomId();
				//
				final String hsSocketHost = LoginServer.getInstance().getLoginServerConfig().getHallServerSocketHost();
				final int hsPort = LoginServer.getInstance().getLoginServerConfig().getHallServerSocketPort();
				String hsLanHost = LoginServer.getInstance().getLoginServerConfig().getHallServerLanHost();
				int hsLanPort = LoginServer.getInstance().getLoginServerConfig().getHallServerLanPort();
				boolean reconnectRet = LoginServer.getInstance().getLanClientManager().connect(hsLanHost, hsLanPort);
				if (reconnectRet) {
					ChannelFuture channelFuture = LoginServer.getInstance().getLanClientManager().sendQq2Gs(hsLanHost,
							hsLanPort, sessionId, fixed_open_id, access_token);
					// 等待结束
					channelFuture.addListener(new ChannelFutureListener() {
						@Override
						public void operationComplete(ChannelFuture channelFuture) throws Exception {
							S2COpenLogin retMsg = new S2COpenLogin(fixed_refresh_token, fixed_open_id, hsSocketHost,
									sessionId, 0, hsPort);
							if (channelFuture.isCancelled()) {
								retMsg.is_success = 2;
							} else if (!channelFuture.isSuccess()) {
								logger.error("", channelFuture.cause());
								retMsg.is_success = 3;
							}
							gamePlayer.writeAndFlush(retMsg.build(gamePlayer.alloc()));
							LoginStat.getInstance().statLogin(fixed_open_id);
						}
					});
				} else {
					S2COpenLogin retMsg = new S2COpenLogin(fixed_refresh_token, fixed_open_id, hsSocketHost, sessionId,
							1, hsPort);
					gamePlayer.writeAndFlush(retMsg.build(gamePlayer.alloc()));
					LoginStat.getInstance().statLogin(fixed_open_id);
				}
			}
		});
	}

	public void loginRaw(final GamePlayer gamePlayer, final String userName, final String pwd) {
		LoginServer.executorService.execute(new Runnable() {
			@Override
			public void run() {
				boolean existUser = LoginAccountDao.getInstance().checkExist(userName, pwd);
				if (!existUser) {
					S2ErrorCode retMsg = new S2ErrorCode(RetCode.LOGIN_NAME_NOT_EXIST.getNumber());
					gamePlayer.writeAndFlush(retMsg.build(gamePlayer.alloc()));
				} else {
					final int uid = LoginAccountDao.getInstance().getUidByNamePwd(userName, pwd);
					final long sessionId = LoginServer.getInstance().generateRandomId();
					//
					final String hsSocketHost = LoginServer.getInstance().getLoginServerConfig()
							.getHallServerSocketHost();
					final int hsPort = LoginServer.getInstance().getLoginServerConfig().getHallServerSocketPort();
					String hsLanHost = LoginServer.getInstance().getLoginServerConfig().getHallServerLanHost();
					int hsLanPort = LoginServer.getInstance().getLoginServerConfig().getHallServerLanPort();
					boolean reconnectRet = LoginServer.getInstance().getLanClientManager().connect(hsLanHost,
							hsLanPort);
					if (reconnectRet) {
						ChannelFuture channelFuture = LoginServer.getInstance().getLanClientManager()
								.sendMessage(hsLanHost, hsLanPort, sessionId, (int) (uid), 1);
						// 等待结束
						channelFuture.addListener(new ChannelFutureListener() {
							@Override
							public void operationComplete(ChannelFuture channelFuture) throws Exception {
								lua.LuaMessageLogin.S2CLogin retMsg = new lua.LuaMessageLogin.S2CLogin(uid,
										hsSocketHost, sessionId, 0, hsPort);
								if (channelFuture.isCancelled()) {
									retMsg.is_success = 2;
								} else if (!channelFuture.isSuccess()) {
									logger.error("", channelFuture.cause());
									retMsg.is_success = 3;
								}
								gamePlayer.writeAndFlush(retMsg.build(gamePlayer.alloc()));
								LoginStat.getInstance().statLogin(userName);
							}
						});
					} else {
						lua.LuaMessageLogin.S2CLogin retMsg = new lua.LuaMessageLogin.S2CLogin(uid, hsSocketHost,
								sessionId, 1, hsPort);
						gamePlayer.writeAndFlush(retMsg.build(gamePlayer.alloc()));
						LoginStat.getInstance().statLogin(userName);
					}
				}
			}
		});
	}

}
